; SE 3F03 Assignment 5 
; Team 03
;
; File: cubic.asm
; Date: 04/06/10
; An assembly program that finds a single real root of a cubic function.

%include "asm_io.inc"
%define a qword [ebp+8]
%define b qword [ebp+16]
%define c qword [ebp+24]
%define root dword [ebp+32]
%define p qword [ebp-8]
%define q qword [ebp-16]
%define u qword [ebp-24]

segment .data

Two dw 2
Three dw 3
Four dw 4
Nine dw 9
TwentySeven dw 27

segment .text
	global asm_main
asm_main:
	push ebp
	mov ebp, esp
	sub esp, 24
	push ebx
	
	;start of p calculation
	fld a				;stack a
	fld a				;stack a, a
	fmulp st1			;stack a*a
	fild word [Three] 	;stack 3, a^2
	fdivp st1			;stack (a^2)/3
	fld b				;stack b, (a^2)/3
	fsubrp st1			;stack b - (a^2)/3
	fstp p			;p = b-(a^2)/3
	;end of p calculation
	
	
	;start of q calculation
	fild word [Nine] 	;stack 9
	fld a				;stack a, 9
	fld b				;stack b, a, 9
	fmulp st1			;stack b*a, 9
	fmulp st1 			;stack b*a*9
	fild word [Two]		;stack 2, b*a*9
	fld a				;stack a, 2, b*a*9
	fld a				;stack a, a, 2, b*a*9
	fld a 				;stack a, a, a, 2, b*a*9
	fmulp st1			;stack a^2, a, 2, b*a*9
	fmulp st1			;stack a^3, 2, b*a*9
	fmulp st1 			;stack 2*a^3, b*a*9
	fsubrp st1			;stack (2*a^3)-(9*b*a)
	fild word [TwentySeven] 	;stack 27, (2*a^3)-(9*b*a)
	fdivp st1			;stack ((2*a^3)-(9*b*a)))/27
	fld c				;stack c, ((2*a^3)-(9*b*a)))/27
	faddp st1			;stack c + ((2*a^3)-(9*b*a)))/27
	fst q			;q = c + ((2*a^3)-(9*b*a)))/27
	;end of calculations of q
	
	
	;start of calculations of u
	fld p				;stack p
	fld p				;stack p, p
	fld p				;stack p, p, p
	fmulp st1			;stack p*p, p
	fmulp st1			;stack p*p*p
	fild word [TwentySeven]	;stack 27, p*p*p
	fdivp st1			;stack p*p*p/27
	fld q				;stack q, p*p*p/27
	fld q				;stack q, q, p*p*p/27
	fmulp st1			;stack q*q, p*p*p/27
	fild word [Four]	;stack 4, q*q, p*p*p/27
	fdivp st1			;stack q*q/4, p*p*p/27
	faddp st1			;stack q*q/4 + p*p*p/27
	
	;compares if positive or negative
	ftst 
	fstsw ax
	sahf
	jb negative
	
positive: 
	fsqrt				;stack root(q*q/4 + p*p*p/27)
	fld q				;stack q, root(q*q/4 + p*p*p/27)
	fild word [Two]		;stack 2, q, root(q*q/4 + p*p*p/27)
	fdivp st1			;stack q/2, root(q*q/4 + p*p*p/27)
	fsubp st1			;stack -q/2 + root(q*q/4 + p*p*p/27)
	
	ftst 		; test if cubed root is negative or positive
	fstsw ax
	sahf
	jb negativeRoot
	
	call cubedRoot	; if positive, calculate the root and store as u
	fstp u
	
	jmp after
	
negativeRoot:	; if negative, calculate the abs root then negate
	fabs
	call cubedRoot
	fchs
	fstp u
	
	jmp after
	;end of calculations for u
	
negative:
	mov eax, 0
	jmp quit
	
after:
	fld a	;stack a
	fild word [Three]	;stack 3, a
	fdivp st1			;stack a/3
	fld p				;stack p, a/3
	fild word [Three]	;stack 3, p, a/3
	fld u				;stack u, 3, p, a/3
	fmulp st1			;stack 3*u, p, a/3
	fdivp st1			;stack p/(3*u), a/3
	faddp st1			;stack p/(3u) + a/3
	fld u				;stack u, p/(3u) + a/3
	fsubrp st1			;stack u - (p/(3u) + a/3)
	mov ebx, root
	fstp qword [ebx]	;move the root into the root location
	mov eax, 1			;return 1
	jmp quit
	
quit:
	pop ebx
	mov esp, ebp
	pop ebp
	ret				
	
cubedRoot:
	fsqrt 		; stack x^(1/2)
	fld st0		;stack x^(1/2), x^(1/2)
	fsqrt		;stack x^(1/4), x^(1/2)
	fld st0		;stack x^(1/4), x^(1/4), x^(1/2)
	fsqrt		;stack x^(1/8), x^(1/4), x^(1/2)
	fld st0		;stack x^(1/8), x^(1/8), x^(1/4), x^(1/2)
	fsqrt		;stack x^(1/16), x^(1/8), x^(1/4), x^(1/2)
	fmulp st1	;stack x^(1/16) * x^(1/8), x^(1/4), x^(1/2)
	fmulp st1	;stack x^(1/16) * x^(1/8) * x^(1/4), x^(1/2)
	fmulp st1	;stack x^(1/16) * x^(1/8) * x^(1/4) * x^(1/2)
	fsqrt		;stack root(x^(1/16) * x^(1/8) * x^(1/4) * x^(1/2))
	
	ret
